<template>
  <div class="search-wrap" ref="searchWrap">
    <Row>
      <Col :span="layoutCol">
        <BoForm
          ref="searchRef"
          :model="model"
          :columns="_columns"
          :col-props="colProps"
          :labelCol="{ span: 9 }"
          :wrapperCol="{ span: 17 }"
        ></BoForm>
      </Col>
      <Col :span="24 - layoutCol === 0 ? 24 : 24 - layoutCol">
        <Flex justify="end">
          <component :is="actions" />
        </Flex>
      </Col>
    </Row>
  </div>
</template>

<script setup lang="tsx">
import { cloneVNode, type Component, computed, reactive, ref } from 'vue';
import { BoForm, useConfigInject, ValueType } from '../../../index';
import type { SearchFormProps } from '../interface';
import { Column } from '../../../Form/src/interface';
import { useElementSize } from '@vueuse/core';
import { ColProps, Space, Row, Col, Flex } from 'ant-design-vue';
import { valueEnumToOptions } from '../../../utils';

defineOptions({
  name: 'SearchForm',
});

const { configProvide } = useConfigInject();

const emits = defineEmits<{
  search: [model: Record<string, any>];
  reset: [model: Record<string, any>];
}>();

const { columns = [] } = defineProps<SearchFormProps>();
const searchRef = ref();
const searchWrap = ref();
const model = reactive({});

const onSearch = async (params = {}) => {
  const result = await searchRef.value?.validate();
  Object.assign(model, params);
  emits('search', { ...result, ...params });
};

const onReset = () => {
  const result = searchRef.value?.resetFields();
  emits('search', result || {});
};

const isExpand = ref(false);
const toggleExpand = () => {
  isExpand.value = !isExpand.value;
};

const { width } = useElementSize(searchRef);
const { width: layoutWidth } = useElementSize(searchWrap);
const colProps = computed<ColProps>(() => {
  if (width.value > 900) return { span: 8 };
  if (width.value > 600) return { span: 12 };
  return { span: 24 };
});

const layoutCol = computed(() => {
  return layoutWidth.value >= 1200
    ? 18
    : layoutWidth.value >= 900
      ? 16
      : layoutWidth.value > 600
        ? 12
        : 24;
});

const getPlaceHolder = (valueType: ValueType) => {
  switch (valueType) {
    case 'input':
    case 'password':
    case 'inputNumber':
      return '请输入';
    case 'dateRange':
      return ['开始时间', '结束时间'];
    case 'cascader':
    case 'select':
    case 'treeSelect':
    case 'datePicker':
      return '请选择';
  }
};

const hideExpand = computed<boolean>(() => {
  const number = width.value >= 900 ? 3 : width.value >= 600 ? 2 : 1;
  const length = columns.filter((item) => !item.hideInSearch).length;
  return length <= number;
});

const actions = computed<Component>(() => {
  const actions = [
    configProvide.renderSearchButton({
      key: 'search',
      onClick: () => onSearch(),
    }),
    configProvide.renderSearchButton({ key: 'reset', onClick: onReset }),
  ];

  if (!hideExpand.value) {
    actions.push(
      isExpand.value
        ? configProvide.renderSearchButton({
            key: 'collapse',
            onClick: toggleExpand,
          })
        : configProvide.renderSearchButton({
            key: 'expand',
            onClick: toggleExpand,
          }),
    );
  }

  return (
    <Space
      v-slots={{
        default: () => actions,
      }}
    ></Space>
  );
});

const _columns = computed<Column[]>(() => {
  const cols: Column[] = columns.reduce((prev, cur) => {
    if (cur.hideInSearch) return prev;
    const valueType =
      cur.valueType === 'status' ? 'select' : cur.valueType || 'input';

    const fieldProps = {
      placeholder: getPlaceHolder(valueType),
    };

    if (Object.keys(cur.valueEnum || {}).length) {
      Object.assign(fieldProps, {
        options: valueEnumToOptions(cur.valueEnum || {}),
      });
    }

    const result = {
      title: cur.title as string,
      dataIndex: cur.dataIndex as string,
      valueType,
      fieldProps,
    };
    // @ts-ignore
    prev.push(result);
    return prev;
  }, []);
  let idx: number;
  width.value >= 900 ? (idx = 3) : width.value >= 600 ? (idx = 2) : (idx = 1);
  return isExpand.value ? cols : cols.splice(0, idx);
});

defineExpose({
  reset() {
    onReset();
  },
  search(params?: Record<string, any>) {
    onSearch(params);
  },
});
</script>
